package Partie3;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;

import java.io.InputStreamReader;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import Partie1.BernoulliParser;

import commun.Review;
import commun.ReviewType;
/**
 * 
 * @author Chengbo
 *
 */
public class MultinomialAnalyserGeneric {
	
	MultinomialParserGeneric statistiques;
	Map<Integer, ReviewType> reviewTypes;
	File f;
	int nbCorrect = 0;
	int nbFault = 0;
	int nbPosiAsNeg =0;
	int nbNegAsPos =0;
	int nbReview = 0;
	double ratio;
	
	int nbUnknow = 0;
	public static void main(String[] args) throws Exception{
		if(args.length < 4)
		{
			System.out.println("Erreur, il faut avoire au au moins deux paramètre.");
			return;
		}
		MultinomialAnalyserGeneric da = new MultinomialAnalyserGeneric(args);
		da.parseReviews(args[3]);
		System.out.println("nombre review: "+da.nbReview+" nb correct: "+ da.nbCorrect +" nb fault: "+ da.nbFault+" ratio: "+da.ratio);
		System.out.println("Positive review as negative: "+ da.nbPosiAsNeg +" Negative review as positive: "+ da.nbNegAsPos);
		da.output("output.txt");
	}
	/**
	 * Constructeur
	 * @throws Exception
	 */
	public MultinomialAnalyserGeneric(String[] args) throws Exception{
		this.reviewTypes = new HashMap<Integer, ReviewType>();
		this.statistiques = new MultinomialParserGeneric(1);
		statistiques.parseFile(args[0]);
		statistiques.parseFile(args[1]);
		statistiques.parseFile(args[2]);
		statistiques.calculProbabilite();
	}
	/**
	 * Sauvegarder l'茅voluation ici
	 * @param filepath l'adresse de fichier 脿 茅crir
	 * @throws IOException
	 */
	public void output(String filepath) throws IOException{
		FileWriter fwTypes = new FileWriter(filepath);//
        BufferedWriter bwTypes = new BufferedWriter(fwTypes);    //
        String myreadline = new String();    
        
        Object[] key_arr = this.reviewTypes.keySet().toArray();  
        Arrays.sort(key_arr);  
        for (Object key : key_arr) {  
            myreadline = "<review id='"+key+ "' class='"+ (ReviewType)this.reviewTypes.get(key)+"'>"+System.getProperty("line.separator");
	        bwTypes.write(myreadline); //
        }  
		bwTypes.flush();    //
		bwTypes.close();
		fwTypes.close();
	}
	/**
	 * @param review review 锟介枲udier
	 * @return le type pronositique
	 * @throws Exception
	 */
	public ReviewType decideReview(Review review) throws Exception{
		double propaPositive =0;
		double propaNegative=0;
		ReviewType typePronostic;
	    Iterator iter = review.wordsMap.entrySet().iterator(); 
	    while (iter.hasNext()) { 
	    	Map.Entry entry = (Map.Entry) iter.next();
	        String key = (String)entry.getKey();
	        if(this.statistiques.PositiveTable.containsKey(key)){
	        	propaPositive += (Double)entry.getValue()*Math.log(this.statistiques.PositiveTable.get(key));
	        }
	        if(this.statistiques.NegativeTable.containsKey(key)){
	         	propaNegative += (Double)entry.getValue()*Math.log(this.statistiques.NegativeTable.get(key));
	        }
	   
	    } 
		if(propaPositive > propaNegative){
			typePronostic = ReviewType.Positive;
		}else{
			typePronostic = ReviewType.Negative;
		}

		return typePronostic;

	}
	
	/**
	 * parser tous les review dans le fichier.
	 * @param filepath o锟絪e trouve le fichier 闁爑di锟�
	 * @throws Exception
	 */
	public  void parseReviews(String filepath) throws Exception{
		File f = new File(filepath); 
		FileInputStream fstream = new FileInputStream(f);
		DataInputStream in = new DataInputStream(fstream);		
		BufferedReader br = new BufferedReader(new InputStreamReader(in));
		String strLine;
		while ((strLine = br.readLine()) != null)   {
			if(strLine.contains("<review") && strLine.contains("id"))
			{
	    		Review unReview = BernoulliParser.parseUnReview(br, strLine); 
	    		this.nbReview++;
	    		ReviewType typePronostic = decideReview(unReview);
	    		this.reviewTypes.put(unReview.id, typePronostic);
	    		
	    		if (unReview.realType!=commun.ReviewType.Unknown) {
	    			//System.out.println("review: "+ unReview.id +" real: "+unReview.realType+" pronostic: "+typePronostic);
		    		if(typePronostic.compareTo(unReview.realType)==0){
		    			this.nbCorrect++;
		    		}else{
		    			if(typePronostic.equals(ReviewType.Positive))
		    				this.nbNegAsPos++;
		    			else
		    				this.nbPosiAsNeg++;
		    			this.nbFault++;
		    		}
				}
			}
		 }
		this.ratio = (double)this.nbCorrect/this.nbReview;
	    br.close();
	    in.close();
	    fstream.close(); 
	}
}
